/*
 * Copyright DimYLiK.
 */

package com.example.myapp.client;

import com.example.myapp.client.components.AddWordButton;
import com.example.myapp.client.components.BaldaTextBox;
import com.example.myapp.client.components.ClearButton;
import com.example.myapp.client.components.DigitTextBox;
import com.example.myapp.client.components.FillFieldButton;
import com.example.myapp.client.components.FindButton;
import com.example.myapp.client.components.InfoButton;
import com.example.myapp.client.components.LanguageButton;
import com.example.myapp.client.components.MinusButton;
import com.example.myapp.client.components.NewGameButton;
import com.example.myapp.client.components.PlusButton;
import com.example.myapp.client.translation.AntiBaldaLanguage;
import com.example.myapp.client.translation.en.AntiBaldaLanguageEn;
import com.example.myapp.client.translation.ru.AntiBaldaLanguageRu;
import com.example.myapp.shared.SavedSessionModel;
import com.example.myapp.shared.Word;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.KeyUpEvent;
import com.google.gwt.event.dom.client.KeyUpHandler;
import com.google.gwt.event.dom.client.MouseDownEvent;
import com.google.gwt.event.dom.client.MouseDownHandler;
import com.google.gwt.event.dom.client.MouseOutEvent;
import com.google.gwt.event.dom.client.MouseOutHandler;
import com.google.gwt.event.dom.client.MouseOverEvent;
import com.google.gwt.event.dom.client.MouseOverHandler;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Anchor;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.PopupPanel;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class AntiBaldaView implements EntryPoint {

    private final AntiBaldaServiceAsync service = GWT.create(AntiBaldaService.class);
    private static final AntiBaldaLanguageRu LANGUAGE_RU = GWT.create(AntiBaldaLanguageRu.class);
    private static final AntiBaldaLanguageEn LANGUAGE_EN = GWT.create(AntiBaldaLanguageEn.class);
    private static final Map<String, AntiBaldaLanguage> LANGUAGES_MAP = createLanguageMap(LANGUAGE_RU, LANGUAGE_EN);

    private String DEFAULT_LANGUAGE = LANGUAGE_RU.label();
    private String LANGUAGE = getLanguageLabel();
    private List<LanguageButton> languageButtons = new ArrayList<LanguageButton>();

    private HorizontalPanel root = new HorizontalPanel();
    private VerticalPanel pole = new VerticalPanel();
    public static final int POLE_SIZE = 5;
    public static final int MIN_LETTERS = 4;
    public static final int MAX_LETTERS = 12;
    public static final int MAX_RESULT = 10;
    public static final String X = ".";
    public static final String MINUS_LETTER = "-";

    private List<List<String>> poleList = new ArrayList<List<String>>();
    private List<List<BaldaTextBox>> poleBaldaTextBoxList = new ArrayList<List<BaldaTextBox>>();
    private BaldaTextBox currentTextBox = null;

    private VerticalPanel usedWordsPanel = new VerticalPanel();
    private List<Word> usedWords = new ArrayList<Word>();
    private TextBox usedWordTextBox = new TextBox();

    private VerticalPanel nonUsedWordsPanel = new VerticalPanel();
    private List<Word> nonUsedWords = new ArrayList<Word>();

    private VerticalPanel resultPanel = new VerticalPanel();
    private VerticalPanel informationPanel = new VerticalPanel();
    private HorizontalPanel wordDescriptionPanel = new HorizontalPanel();
    private FindButton findButton = new FindButton();
    private NewGameButton newGameButton = new NewGameButton();
    private AddWordButton addWordButton = new AddWordButton();
    private DigitTextBox maxWordsTextBox = new DigitTextBox(MAX_RESULT, 50, null);
    private DigitTextBox minLettersTextBox = new DigitTextBox(MIN_LETTERS, MIN_LETTERS, Boolean.FALSE);
    private DigitTextBox maxLettersTextBox = new DigitTextBox(7, MAX_LETTERS, Boolean.TRUE);
    private long time = 0;

    private static PopupPanel abcPopup = new PopupPanel();

    private Label usedWordsLabel = new Label();
    private Label nonUsedWordsLabel = new Label();
    private Label getMaxLabel = new Label();
    private Label wordsFromLabel = new Label();
    private Label wordsToLabel = new Label();
    private Label lettersLabel = new Label();
    public static final String WWW_ADDRESS = "http://antibalda.googlecode.com";


    public void onModuleLoad() {
        initStructure();

        initPole();

        checkSession();

        initVocabulary();

        initIpAddress();

        updateAllTitles();

        RootPanel.get("antiBaldaContainer").add(root);

        updateMainLogo();
    }

    private void initStructure() {
        root.clear();

        // init Pole and Find button
        createFindButton();
        createClearButton();
        HorizontalPanel buttonsPanel = new HorizontalPanel();
        buttonsPanel.add(findButton);
        buttonsPanel.add(newGameButton);

        addLanguageButtons(buttonsPanel, LANGUAGES_MAP);

        informationPanel.clear();
        VerticalPanel poleWithButtons = new VerticalPanel();
        poleWithButtons.add(pole);
        poleWithButtons.add(initMinMaxLettersPannel());
        poleWithButtons.add(buttonsPanel);
        poleWithButtons.add(informationPanel);
        root.add(poleWithButtons);

        root.add(updateUsedAndNonusedWordsPanel());

        updateResultPanel();

        updateAbcPopup();

        root.add(resultPanel);

    }

    private void addLanguageButtons(HorizontalPanel buttonsPanel, final Map<String, AntiBaldaLanguage> languagesMap) {
        languageButtons.clear();
        for (final String label : languagesMap.keySet()) {
            AntiBaldaLanguage language = languagesMap.get(label);
            final LanguageButton languageButton = new LanguageButton(language.label(), language.title(), LANGUAGE.equals(label));
            languageButton.addClickHandler(new ClickHandler() {
                public void onClick(ClickEvent event) {
                    languageButton.setActiveStyle();
                    LANGUAGE = label;
                    for (LanguageButton languageButton : languageButtons) {
                        languageButton.updateActiveStyle(LANGUAGE.equals(languageButton.getText()));
                    }
                    updateAllTitles();
                }
            });
            languageButtons.add(languageButton);
            buttonsPanel.add(languageButton);
        }
    }

    private void updateAllTitles() {
        AntiBaldaLanguage currentLanguage = getCurrentLanguage();

        usedWordsLabel.setText(currentLanguage.userWords());
        nonUsedWordsLabel.setText(currentLanguage.nonUserWords());

        getMaxLabel.setText(currentLanguage.getMax());
        wordsFromLabel.setText(currentLanguage.wordsFrom());
        wordsToLabel.setText(currentLanguage.wordsTo());
        lettersLabel.setText(currentLanguage.letters());

        findButton.updateButton(currentLanguage.buttonFindLabel(), currentLanguage.buttonFindTitle());
        newGameButton.updateButton(currentLanguage.buttonNewGameLabel(), currentLanguage.buttonNewGameTitle());
        addWordButton.updateButton(currentLanguage.buttonAddWordLabel(), currentLanguage.buttonAddWordTitle());

        updateAbcPopup();
    }

    private HorizontalPanel initMinMaxLettersPannel() {
        maxWordsTextBox.addCustomChangeHandler(null);
        minLettersTextBox.addCustomChangeHandler(maxLettersTextBox);
        maxLettersTextBox.addCustomChangeHandler(minLettersTextBox);

        HorizontalPanel minMaxPanel = new HorizontalPanel();
        minMaxPanel.add(getMaxLabel);
        minMaxPanel.add(maxWordsTextBox);
        minMaxPanel.add(wordsFromLabel);
        minMaxPanel.add(minLettersTextBox);
        minMaxPanel.add(wordsToLabel);
        minMaxPanel.add(maxLettersTextBox);
        minMaxPanel.add(lettersLabel);
        return minMaxPanel;
    }

    private void updateResultPanel() {
        resultPanel.addStyleName("resultPanel");
    }

    private VerticalPanel updateUsedAndNonusedWordsPanel() {
        usedWords.clear();
        nonUsedWords.clear();

        VerticalPanel usedWordsFullPanel = new VerticalPanel();
        addWordButton.addClickHandler(new ClickHandler() {
            public void onClick(ClickEvent event) {
                String usedWord = usedWordTextBox.getValue();
                if (usedWord != null && usedWord.length() > 0) {
                    Word word = new Word(usedWord.toLowerCase());
                    addWordToUsedWords(word);
                }
                usedWordTextBox.setValue(null);
            }
        });

        wordDescriptionPanel.addStyleName("wordDescriptionPanel");
        usedWordsFullPanel.add(wordDescriptionPanel);

        InfoButton infoButton = new InfoButton(getCurrentLanguage().showWordDescription());
        infoButton.addClickHandler(getInfoButtonClickHandler(usedWordTextBox));

        HorizontalPanel addButtonWithTextBoxPanel = new HorizontalPanel();
        addButtonWithTextBoxPanel.add(usedWordTextBox);
        addButtonWithTextBoxPanel.add(infoButton);
        addButtonWithTextBoxPanel.add(addWordButton);
        usedWordsFullPanel.add(addButtonWithTextBoxPanel);

        VerticalPanel usedWordsWithLabelPanel = new VerticalPanel();
        usedWordsWithLabelPanel.addStyleName("panelStylePlus");
        usedWordsWithLabelPanel.add(usedWordsLabel);
        usedWordsWithLabelPanel.add(usedWordsPanel);

        VerticalPanel nonUsedWordsWithLabelPanel = new VerticalPanel();
        nonUsedWordsWithLabelPanel.addStyleName("panelStyleMinus");
        nonUsedWordsWithLabelPanel.add(nonUsedWordsLabel);
        nonUsedWordsWithLabelPanel.add(nonUsedWordsPanel);

        HorizontalPanel usedAndNonusedPanel = new HorizontalPanel();
        usedAndNonusedPanel.add(usedWordsWithLabelPanel);
        usedAndNonusedPanel.add(nonUsedWordsWithLabelPanel);
        usedWordsFullPanel.add(usedAndNonusedPanel);

        return usedWordsFullPanel;
    }

    private void addWordToUsedWords(Word word) {
        if (!usedWords.contains(word) && !nonUsedWords.contains(word)) {
            usedWords.add(word);
            usedWordsPanel.add(createUsedWordPanel(word));
        }
    }

    private void addWordToNonUsedWords(Word word) {
        if (!nonUsedWords.contains(word) && !usedWords.contains(word)) {
            nonUsedWords.add(word);
            nonUsedWordsPanel.add(createNonUsedWordPanel(word));
        }
    }

    private HorizontalPanel createUsedWordPanel(final Word word) {
        final HorizontalPanel result = new HorizontalPanel();
        MinusButton minusButton = new MinusButton(getCurrentLanguage().addRemoveToNonUsedWords());
        minusButton.addClickHandler(new ClickHandler() {
            public void onClick(ClickEvent event) {
                usedWords.remove(word);
                usedWordsPanel.remove(result);
            }
        });
        final FillFieldButton fillFieldButton = new FillFieldButton(getCurrentLanguage().addMissingLetter(), word.getMove());
        fillFieldButton.addClickHandler(new ClickHandler() {
            public void onClick(ClickEvent event) {
                fillField(word);
                fillFieldButton.setDisabled();
            }
        });
        InfoButton infoButton = new InfoButton(getCurrentLanguage().showWordDescription());
        infoButton.addClickHandler(getInfoButtonClickHandler(word.getWord()));

        result.add(infoButton);
        result.add(minusButton);
        result.add(fillFieldButton);
        result.add(getWordLabel(word));
        return result;
    }

    private ClickHandler getInfoButtonClickHandler(final TextBox usedWordTextBox) {
        return new ClickHandler() {
            public void onClick(ClickEvent event) {
                String stringWord = usedWordTextBox.getValue();
                if (stringWord != null && stringWord.length() > 0) {
                    final String finalStringWord = stringWord.toLowerCase();
                    LoadingIndicator.show(getCurrentLanguage().loading() + " <" + finalStringWord + "> " + getCurrentLanguage().description() + "...");
                    service.getWordDescription(finalStringWord, new AsyncCallback<String>() {
                        public void onSuccess(String result) {
                            if (result != null) {
                                addToWordDescriptionPanel(finalStringWord + " - " + result);
                            } else {
                                addToWordDescriptionPanel(getCurrentLanguage().word() + " <" + finalStringWord + "> " + getCurrentLanguage().descriptionNotFound());
                            }
                            LoadingIndicator.hide();
                        }

                        public void onFailure(Throwable caught) {
                            addToWordDescriptionPanel("<" + finalStringWord + "> " + getCurrentLanguage().descriptionFindingError() + "...");
                            LoadingIndicator.hide();
                        }
                    });
                }
            }
        };
    }

    private ClickHandler getInfoButtonClickHandler(final String stringWord) {
        return new ClickHandler() {
            public void onClick(ClickEvent event) {
                LoadingIndicator.show(getCurrentLanguage().loading() + "<" + stringWord + "> " + getCurrentLanguage().description() + "...");
                service.getWordDescription(stringWord, new AsyncCallback<String>() {
                    public void onSuccess(String result) {
                        if (result != null) {
                            addToWordDescriptionPanel(stringWord + " - " + result);
                        } else {
                            addToWordDescriptionPanel(getCurrentLanguage().word() + " <" + stringWord + "> " + getCurrentLanguage().descriptionNotFound());
                        }
                        LoadingIndicator.hide();
                    }

                    public void onFailure(Throwable caught) {
                        addToWordDescriptionPanel("<" + stringWord + "> " + getCurrentLanguage().descriptionFindingError() + "...");
                        LoadingIndicator.hide();
                    }
                });
            }
        };
    }

    private void addToWordDescriptionPanel(String text) {
        wordDescriptionPanel.clear();
        wordDescriptionPanel.add(new Label(text));

        ClearButton clearButton = new ClearButton(getCurrentLanguage().clearDescription());
        clearButton.addClickHandler(new ClickHandler() {
            public void onClick(ClickEvent event) {
                wordDescriptionPanel.clear();
            }
        });
        wordDescriptionPanel.add(clearButton);
    }

    private HorizontalPanel createNonUsedWordPanel(final Word word) {
        final HorizontalPanel panel = new HorizontalPanel();
        PlusButton plusButton = new PlusButton(getCurrentLanguage().addRemoveToUsedWords());
        plusButton.addClickHandler(new ClickHandler() {
            public void onClick(ClickEvent event) {
                nonUsedWords.remove(word);
                nonUsedWordsPanel.remove(panel);
            }
        });
        InfoButton infoButton = new InfoButton(getCurrentLanguage().showWordDescription());
        infoButton.addClickHandler(getInfoButtonClickHandler(word.getWord()));

        panel.add(infoButton);
        panel.add(plusButton);
        panel.add(getWordLabel(word));
        return panel;
    }

    private void initVocabulary() {
        final AntiBaldaLanguage currentLanguage = getCurrentLanguage();
        informationPanel.add(new Label(currentLanguage.welcomeToAntiBalda()));
        informationPanel.add(new Anchor(currentLanguage.www() + ": " + WWW_ADDRESS, WWW_ADDRESS));
        informationPanel.add(new Label(currentLanguage.staticVocabularyLoadingStarted()));
        LoadingIndicator.show(currentLanguage.loadingVocabulary());
        service.initVocabulary(new AsyncCallback<Integer>() {
            public void onSuccess(Integer result) {
                if (result == null) {
                    informationPanel.add(new Label(currentLanguage.noVocabularyLoaded()));
                } else {
                    informationPanel.add(new Label("<" + result + "> " + currentLanguage.wordsLoadedAndSortedSuccessfully()));
                }
                LoadingIndicator.hide();
            }

            public void onFailure(Throwable caught) {
                informationPanel.add(new Label(currentLanguage.noVocabularyLoaded()));
                LoadingIndicator.hide();
            }
        });
    }

    private void checkSession() {
        service.checkSession(new AsyncCallback<SavedSessionModel>() {
            public void onSuccess(SavedSessionModel savedSessionModel) {
                if (savedSessionModel == null) {
                    informationPanel.add(new Label(getCurrentLanguage().noSavedSessionWasFound()));
                } else {
                    informationPanel.add(new Label(getCurrentLanguage().sessionWasSuccessfullyRestored()));
                    redrawPole(savedSessionModel.getPoleList());

                    redrawUsed(savedSessionModel.getUsedWords());
                    redrawNonUsed(savedSessionModel.getNonUsedWords());
                }
                LoadingIndicator.hide();
            }

            public void onFailure(Throwable caught) {
                informationPanel.add(new Label(getCurrentLanguage().failureDuringSessionChecking()));
                LoadingIndicator.hide();
            }
        });
    }

    private void redrawUsed(List<Word> savedUsedWords) {
        usedWords.clear();
        usedWordsPanel.clear();
        for (Word word : savedUsedWords) {
            usedWords.add(word);
            usedWordsPanel.add(createUsedWordPanel(word));
        }
    }

    private void redrawNonUsed(List<Word> savedNonUsedWords) {
        nonUsedWords.clear();
        nonUsedWordsPanel.clear();
        for (Word word : savedNonUsedWords) {
            nonUsedWords.add(word);
            nonUsedWordsPanel.add(createNonUsedWordPanel(word));
        }
    }

    private void redrawPole(List<List<String>> result) {
        poleList = result;

        for (int i = 0; i < POLE_SIZE; i++) {
            for (int j = 0; j < POLE_SIZE; j++) {
                String letter = poleList.get(i).get(j);
                BaldaTextBox textBox = poleBaldaTextBoxList.get(i).get(j);
                textBox.setValue(X.equals(letter) ? "" : letter);
            }
        }
    }

    private void initPole() {
        pole.clear();
        poleBaldaTextBoxList.clear();

        for (int i = 0; i < POLE_SIZE; i++) {
            List<String> poleRow = new ArrayList<String>();
            List<BaldaTextBox> baldaTextBoxRow = new ArrayList<BaldaTextBox>();
            HorizontalPanel horizontalPanelRow = new HorizontalPanel();
            for (int j = 0; j < POLE_SIZE; j++) {
                poleRow.add(X);

                final BaldaTextBox textBox = new BaldaTextBox(i, j, "");
                textBox.addKeyUpHandler(new KeyUpHandler() {
                    public void onKeyUp(KeyUpEvent event) {
                        String value = textBox.getValue();
                        String letter;
                        if (value == null || value.length() == 0) {
                            letter = X;
                        } else if (value.length() > 1) {
                            letter = value.substring(0, 1);
                        } else {
                            letter = value;
                        }
                        textBox.setValue(X.equals(letter) ? "" : letter);

                        int I = textBox.getI();
                        int J = textBox.getJ();
                        poleList.get(I).set(J, letter);
                    }
                });
                textBox.addMouseDownHandler(new MouseDownHandler() {
                    public void onMouseDown(MouseDownEvent event) {
                        currentTextBox = textBox;
                        showAbcPopup(event.getClientX(), event.getClientY());
                    }
                });
                baldaTextBoxRow.add(textBox);
                horizontalPanelRow.add(textBox);
            }
            poleList.add(poleRow);
            poleBaldaTextBoxList.add(baldaTextBoxRow);
            pole.add(horizontalPanelRow);
        }
    }

    private void showAbcPopup(int clientX, int clientY) {
        abcPopup.setPopupPosition(clientX, clientY);
        abcPopup.show();
    }

    private void updateAbcPopup() {
        abcPopup.clear();
        HorizontalPanel abcButtonPanel = new HorizontalPanel();
        HorizontalPanel abcOneHalfPanel = new HorizontalPanel();
        HorizontalPanel abcSecondHalfPanel = new HorizontalPanel();
        String abc = MINUS_LETTER + getCurrentLanguage().abc();
        for (int i = 0; i < abc.length(); i++) {
            final String letter = abc.substring(i, i + 1);
            Button letterButton = new Button(letter);
            letterButton.addClickHandler(new ClickHandler() {
                public void onClick(ClickEvent event) {
                    currentTextBox.setValue(MINUS_LETTER.equals(letter) ? "" : letter);

                    int I = currentTextBox.getI();
                    int J = currentTextBox.getJ();
                    poleList.get(I).set(J, MINUS_LETTER.equals(letter) ? "" : letter);

                    abcPopup.hide();
                }
            });
            if (i <= (abc.length() / 2)) {
                abcOneHalfPanel.add(letterButton);
            } else {
                abcSecondHalfPanel.add(letterButton);
            }
        }
        VerticalPanel abcVerticalPanel = new VerticalPanel();
        abcVerticalPanel.add(abcOneHalfPanel);
        abcVerticalPanel.add(abcSecondHalfPanel);
        abcButtonPanel.add(abcVerticalPanel);
        abcPopup.add(abcButtonPanel);
    }

    private void createFindButton() {
        findButton.addClickHandler(new ClickHandler() {
            public void onClick(ClickEvent event) {
                Date date = new Date();
                final long timeBefore = date.getTime();
                LoadingIndicator.show(getCurrentLanguage().findingWords());
                Integer minLetters = Integer.valueOf(minLettersTextBox.getValue());
                Integer maxLetters = Integer.valueOf(maxLettersTextBox.getValue());
                Integer maxWords = Integer.valueOf(maxWordsTextBox.getValue());
                SavedSessionModel savedSessionModel = new SavedSessionModel(poleList, usedWords, nonUsedWords);
                service.findWords(savedSessionModel, minLetters, maxLetters, maxWords, new AsyncCallback<List<Word>>() {
                    public void onSuccess(List<Word> resultList) {
                        Date date = new Date();
                        time = date.getTime() - timeBefore;

                        updateResultPanel(resultList, true);
                        LoadingIndicator.hide();
                    }

                    public void onFailure(Throwable caught) {
                        Date date = new Date();
                        time = date.getTime() - timeBefore;

                        updateResultPanel(new ArrayList<Word>(), false);
                        LoadingIndicator.hide();
                    }
                });
            }
        });
    }

    private void createClearButton() {
        newGameButton.addClickHandler(new ClickHandler() {
            public void onClick(ClickEvent event) {
                informationPanel.add(new Label(getCurrentLanguage().clearingCurrentGame()));

                usedWords.clear();
                usedWordsPanel.clear();
                usedWordTextBox.setValue(null);
                nonUsedWords.clear();
                nonUsedWordsPanel.clear();

                resultPanel.clear();
                wordDescriptionPanel.clear();

                abcPopup.hide();

                poleList.clear();
                initPole();
            }
        });
    }

    private void updateResultPanel(List<Word> resultList, boolean success) {
        resultPanel.clear();
        resultList.removeAll(usedWords);
        AntiBaldaLanguage currentLanguage = getCurrentLanguage();
        String loadingTime = (time > 1000) ? (time / 1000 + " " + currentLanguage.seconds() + ":") : (time + " " + currentLanguage.milliseconds() + ":");
        resultPanel.add(new Label(resultList.size() + " " + currentLanguage.wordsFoundIn() + " " + loadingTime));
        if (success) {
            int lastLength = -1;
            for (final Word word : resultList) {
                final String wordString = word.getWord();
                final HorizontalPanel resultWordPanel = new HorizontalPanel();
                PlusButton plusButton = new PlusButton(getCurrentLanguage().addRemoveToUsedWords());
                plusButton.addClickHandler(new ClickHandler() {
                    public void onClick(ClickEvent event) {
                        addWordToUsedWords(word);
                        resultPanel.remove(resultWordPanel);
                    }
                });
                MinusButton minusButton = new MinusButton(getCurrentLanguage().addRemoveToNonUsedWords());
                minusButton.addClickHandler(new ClickHandler() {
                    public void onClick(ClickEvent event) {
                        addWordToNonUsedWords(word);
                        resultPanel.remove(resultWordPanel);
                    }
                });
                int len = wordString.length();
                if (len != lastLength) {
                    lastLength = len;
                    VerticalPanel resultHeaderPanel = new VerticalPanel();
                    resultHeaderPanel.add(new Label(" "));
                    resultHeaderPanel.add(new Label(" " + len + " " + currentLanguage.lettersWords() + ":"));
                    resultHeaderPanel.add(new Label("--------------------"));
                    resultPanel.add(resultHeaderPanel);
                }
                InfoButton infoButton = new InfoButton(getCurrentLanguage().showWordDescription());
                infoButton.addClickHandler(getInfoButtonClickHandler(word.getWord()));

                resultWordPanel.add(infoButton);
                resultWordPanel.add(plusButton);
                resultWordPanel.add(minusButton);
                resultWordPanel.add(getWordLabel(word));
                resultPanel.add(resultWordPanel);
            }
        } else {
            resultPanel.add(new Label(currentLanguage.sorryFindingError()));
            int maxLetters = Integer.valueOf(maxLettersTextBox.getValue());
            resultPanel.add(new Label(currentLanguage.tryToMinimizeMaxLettersValueFrom() + " " + maxLetters + " " +
                    currentLanguage.wordsTo() + " " + (maxLetters - 1) + "."));
        }
    }

    private void showMoves(List<List<Integer>> moves, String styleName) {
        for (List<Integer> move : moves) {
            int i = move.get(0);
            int j = move.get(1);
            poleBaldaTextBoxList.get(i).get(j).setStyleName(styleName);
        }
    }

    private void fillField(Word word) {
        String move = word.getMove();
        List<List<Integer>> moves = Word.parseMoves(move);
        for (int x = 0; x < moves.size(); x++) {
            List<Integer> currentMove = moves.get(x);
            int i = currentMove.get(0);
            int j = currentMove.get(1);
            BaldaTextBox textBox = poleBaldaTextBoxList.get(i).get(j);
            String value = textBox.getValue();
            if (value == null || value.length() == 0) {
                String wordString = word.getWord();
                String letter = wordString.substring(x, x + 1);
                textBox.setValue(letter);
                poleList.get(i).set(j, letter);
            }
        }
    }

    public Label getWordLabel(Word word) {
        Label label = new Label(word.getWord());
        String move = word.getMove();
        if (move != null) {
            label.setTitle(getCurrentLanguage().moves() + ": " + move);
            final List<List<Integer>> moves = Word.parseMoves(move);
            label.addMouseOverHandler(new MouseOverHandler() {
                public void onMouseOver(MouseOverEvent event) {
                    showMoves(moves, BaldaTextBox.TEXT_BOX_STYLE_SHOW_MOVE);
                }
            });
            label.addMouseOutHandler(new MouseOutHandler() {
                public void onMouseOut(MouseOutEvent event) {
                    showMoves(moves, BaldaTextBox.TEXT_BOX_STYLE);
                }
            });

        } else {
            label.setTitle(getCurrentLanguage().addedByUser());
        }
        return label;
    }

    private void initIpAddress() {
        service.initIpAddress(new AsyncCallback<String>() {
            public void onSuccess(String result) {
                informationPanel.add(new Label(result));
            }

            public void onFailure(Throwable caught) {
//                informationPanel.add(new Label(getCurrentLanguage().IPadressFindingError()));
            }
        });
    }

    private void updateMainLogo() {
        HorizontalPanel logoPanel = new HorizontalPanel();
        logoPanel.add(new Image(ImageResources.INSTANCE.logo()));
        RootPanel.get("antiBaldaLogo").add(logoPanel);
    }

    private String getLanguageLabel() {
        service.getSavedLanguage(DEFAULT_LANGUAGE, new AsyncCallback<String>() {
            public void onSuccess(String result) {
                if (LANGUAGES_MAP.containsKey(result)) {
                    LANGUAGE = result;
                } else {
                    LANGUAGE = DEFAULT_LANGUAGE;
                }
            }

            public void onFailure(Throwable caught) {
                LANGUAGE = DEFAULT_LANGUAGE;
            }
        });
        return DEFAULT_LANGUAGE;
    }

    private AntiBaldaLanguage getCurrentLanguage() {
        return LANGUAGES_MAP.get(LANGUAGE);
    }

    private static HashMap<String, AntiBaldaLanguage> createLanguageMap(AntiBaldaLanguage... languages) {
        HashMap<String, AntiBaldaLanguage> languageHashMap = new HashMap<String, AntiBaldaLanguage>();
        for (AntiBaldaLanguage language : languages) {
            languageHashMap.put(language.label(), language);
        }
        return languageHashMap;
    }
}